package com.zlp.stack;

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;

/**
 * 演示方法区内存溢出
 */
public class MethodArea_1 extends ClassLoader{
    public static void main(String[] args) {
        //methodArea();
        test();
    }

    /**
     * 常量池中的信息，都会被加载到运行时常量池中，但此时a,b,ab,都是符号，还没变成java字符串对象
     */
    public static void test(){
        String s1 = "a";//懒惰加载，使用的时候才会创建对象
        String s2 = "b";
        String s3 = s1 + s2;//底层使用new StringBuilder.append().append().toString
        String s4 = "a" + "b";//结果在编译期间已经确定的话，会被优化，对于两个常量拼接，直接编译成s4 = "ab";
    }

    /**
     * 演示方法区内存溢出
     * -xx:MaxMetaspaceSize=8m
     */
    private static void methodArea(){
        int j = 0;
        try {
            MethodArea_1 test = new MethodArea_1();
            for (;j<10000;j++){
                //用代码的方式生成类的二进制字节码
                ClassWriter cw = new ClassWriter(0);
                //版本号，访问修饰符，类名，包名，类的父类，实现的接口名称
                cw.visit(Opcodes.V1_8,Opcodes.ACC_PUBLIC,"Class"+j,null,"java/lang/Object",null);
                //返回类的字节码文件
                byte[] code = cw.toByteArray();
                //只执行了类的加载
                test.defineClass("Class"+j,code,0,code.length);
            }
        }finally {
            System.out.println(j);
        }
    }
}
